package com.to8to.autotask.newlundan;

import static com.to8to.es.dao.ESTypes.TYPE_APPLY;
import static com.to8to.es.dao.ESTypes.TYPE_COMPANY;
import static org.elasticsearch.search.sort.SortOrder.ASC;

import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.index.query.BoolFilterBuilder;
import org.elasticsearch.index.query.FilterBuilders;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.to8to.autotask.newlundan.entity.ExtObj;
import com.to8to.autotask.newlundan.entity.FCom;
import com.to8to.autotask.newlundan.entity.ZXBOrder;
import com.to8to.autotask.util.DBUtil;
import com.to8to.autotask.util.Utils;
import com.to8to.commons.utils.DateUtil;
import com.to8to.commons.utils.StringUtil;
import com.to8to.es.dao.ESUtil;
import com.to8to.es.util.LogUtil;

public class AllocateProcess
{
    private static final Logger logger = LoggerFactory.getLogger(AllocateProcess.class);

    /**
     * 开启新版轮标模式的城市
     */
    private static final List<Integer> NEW_ZXBCITY = Arrays.asList(1130);

    public static void allocate(int cityid) throws SQLException
    {
        if (cityid == 0)
            throw new IllegalStateException("param cityid is 0!");

        List<ExtObj> list = getProject(cityid);
        if (Utils.isNullOrEmpty(list))
            return;

        Connection connect = DBUtil.getConnection();
        insertZXBOrderLog(1, list.get(0), cityid, list.size(), connect);

        for (ExtObj ext : list)
        {
            ZXBOrder order = getOrderInfoByTid(ext.getTid());
            String struid = Utils.append(order.getHead_order(), order.getEnd_order());

            List<Integer> oldUid = Utils.parseIntegerList(struid, ",");
            List<Integer> newVersionUid = new ArrayList<Integer>(); //新版本轮标模式
            List<Integer> ATypeUid = new ArrayList<Integer>(); //A类公司(有monthlimit公司)
            List<Integer> unsetUid = new ArrayList<Integer>(); //不参与本次分配的公司  & 已经分配的公司
            List<Integer> vipUid = new ArrayList<Integer>(); //会员制项目费公司
            List<Integer> coreUid = new ArrayList<Integer>(); //核心客户

            Map<Integer, Integer> dayOffMap = new HashMap<Integer, Integer>();
            Map<Integer, FCom> fcomMap = new HashMap<Integer, FCom>();

            //参与本次轮表的所有公司。
            String newStrUid = Utils.append(struid, ext.getCompanySort());
            //轮标价位段
            String haveTbnumsField = "have_tbnums" + (order.getPriceleve() == 1 ? "" : ("_" + order.getPriceleve()));

            String sale_zxborder = null;
            //会员制项目费公司
            if (ext.getSid() > 0)
            {
                sale_zxborder = getSaleInfo(ext.getSid());
                newStrUid = Utils.append(newStrUid, sale_zxborder);
                if (!StringUtil.isEmpty(sale_zxborder))
                    vipUid.addAll(Utils.parseIntegerList(sale_zxborder, ","));
            }

            //获取轮标装修公司的信息；遍历公司，并根据不同分情况分别放入不同的List中
            Map<Integer, FCom> comMap = getCompaynInfo(newStrUid);
            handlerFComInfo(comMap.values(), dayOffMap, fcomMap, ATypeUid, vipUid, unsetUid, ext);

            List<String> zxbMsgList = new ArrayList<String>();
            List<Integer> weekdayList = new ArrayList<Integer>();
            List<Integer> companySortList = new ArrayList<Integer>();
            //新版的轮标城市(重置原有队列排序)
            if (NEW_ZXBCITY.contains(cityid))
            {
                if (!StringUtil.isEmpty(ext.getCompanySort()))
                    struid = ext.getCompanySort();
                if (!StringUtil.isEmpty(ext.getSendmobiletime())) //量房时间
                {
                    String[] sendTimeArr = ext.getSendmobiletime().split(",");
                    String msg = "量房时间：" + sendTimeArr[0];
                    int weekday = Utils.getWeekday(sendTimeArr[0]);
                    zxbMsgList.add(msg);
                    weekdayList.add(weekday);
                }
                if (!StringUtil.isEmpty(struid))
                {
                    companySortList.addAll(Utils.parseIntegerList(struid, ","));
                    //去掉原轮表队列中不存在的公司
                    for (Integer uid : companySortList)
                    {
                        if (oldUid.contains(uid))
                            newVersionUid.add(uid);
                    }
                    //恢复，排到后面
                    for (Integer uid : oldUid)
                    {
                        if (!newVersionUid.contains(uid))
                            newVersionUid.add(uid);
                    }
                    oldUid = newVersionUid;
                    struid = Utils.collect2Str(newVersionUid);
                }
            }

            //施工资质
            if (!StringUtil.isEmpty(ext.getSg_zz()) && oldUid.size() > 0)
            {
                List<String> sgzzList = getSgzzList(ext.getSg_zz());
                if (sgzzList != null)
                {
                    for (Integer uid : oldUid)
                    {
                        FCom com = comMap.get(uid);
                        if (!sgzzList.contains(com.getAptrank()))
                            unsetUid.add(uid);
                    }
                }
            }

            int lundanNum = 3;
            List<Integer> lundanList = new ArrayList<Integer>();
            List<Integer> newUid = new ArrayList<Integer>(oldUid);
            //如果有头牌的话，头牌占一个名额
            if (ext.getToupai_uid() > 0)
            {
                lundanNum--;
                lundanList.add(ext.getToupai_uid());
                unsetUid.add(ext.getToupai_uid());
            }
            //使用了保底牌的用户 ??????????????????
            if (ext.getBaodi_uid() > 0)
            {
                lundanNum--;
                unsetUid.add(ext.getBaodi_uid());
            }

            //小区轮标分配（会员制项目费公司、楼盘承包商），本次轮到的放到队列后面，并重新更新，相当于轮流
            if (ext.getSid() > 0 && !StringUtil.isEmpty(sale_zxborder))
            {
                Iterator<Integer> it = vipUid.iterator();
                List<Integer> tmp = new ArrayList<Integer>();
                while (it.hasNext())
                {
                    Integer uid = it.next();
                    if (lundanNum > 0 && !unsetUid.contains(uid))
                    {
                        lundanList.add(uid);
                        unsetUid.add(uid);
                        lundanNum--;
                        it.remove();
                        tmp.add(uid);
                    }
                    if (lundanNum == 0)
                        break;
                }
                vipUid.addAll(tmp);
                DBUtil.updateField("to8to_sale", "zxborder", Utils.collect2Str(vipUid), "sid", String.valueOf(ext.getSid()));
            }

            if (!StringUtil.isEmpty(struid) && NEW_ZXBCITY.contains(cityid))
            {
                for (Integer uid : companySortList)
                {

                }
            }
        }
    }

    private static List<String> getSgzzList(String sg_zz)
    {
        if (sg_zz.equals("一级"))
            return Arrays.asList(sg_zz);
        if (sg_zz.equals("二级"))
            return Arrays.asList("一级", sg_zz);
        if (sg_zz.equals("三级"))
            return Arrays.asList("一级", "二级", sg_zz);
        return null;
    }

    private static void handlerFComInfo(Collection<FCom> coms, Map<Integer, Integer> dayOffMap, Map<Integer, FCom> fcomMap, List<Integer> ATypeUid,
            List<Integer> vipUid, List<Integer> unsetUid, ExtObj ext)
    {
        for (FCom com : coms)
        {
            dayOffMap.put(com.getId(), com.getDayoff());
            fcomMap.put(com.getId(), com);
            if (com.getMonthlylimit() > 0)
                ATypeUid.add(com.getId());

            if (vipUid.size() > 0 && vipUid.contains(com.getId()))
            {
                if (com.getCancost() < 200) //小区轮标公司余额小于200不轮标
                    unsetUid.add(com.getId());
            }
            else if (com.getMonthlylimit() > 0)
            {
                if (com.getCancost() < 298 && com.getHave_tbnums() < 1)
                    unsetUid.add(com.getId());
            }
            else if (com.getCancost() < ext.getOprice() && com.getHave_tbnums() < 1)
            {
                unsetUid.add(com.getId());
            }
        }
    }

    private static Map<Integer, FCom> getCompaynInfo(String uidStr)
    {
        Map<Integer, FCom> result = new HashMap<Integer, FCom>();

        BoolFilterBuilder boolFilter = FilterBuilders.boolFilter();
        boolFilter.must(FilterBuilders.termsFilter("id", Arrays.asList(uidStr.split(","))));
        QueryBuilder queryBuilder = QueryBuilders.filteredQuery(QueryBuilders.matchAllQuery(), boolFilter);
        SearchResponse resp = ESUtil.es.prepareSearch().setTypes(TYPE_COMPANY).setQuery(queryBuilder).setSize(1).execute().actionGet();
        SearchHit[] hits = resp.getHits().getHits();
        for (SearchHit hit : hits)
        {
            Map<String, Object> map = hit.getSource();
            FCom com = new FCom();
            com.setId((Integer) (map.get("id")));
            com.setCancost((Double) (map.get("cancost")));
            com.setDayoff((Integer) (map.get("dayoff")));
            com.setMonthlylimit((Integer) (map.get("monthlylimit")));
            com.setHave_tbnums((Integer) (map.get("have_tbnums")));
            com.setHave_tbnums_2((Integer) (map.get("have_tbnums_2")));
            com.setHave_tbnums_2((Integer) (map.get("have_tbnums_3")));
            com.setHave_tbnums_2((Integer) (map.get("have_tbnums_4")));
            com.setHave_tbnums_2((Integer) (map.get("have_tbnums_5")));
            com.setHave_tbnums_2((Integer) (map.get("have_tbnums_6")));
            com.setHave_tbnums_2((Integer) (map.get("have_tbnums_7")));

            result.put(com.getId(), com);
        }
        return result;
    }

    private static String getSaleInfo(int sid)
    {
        Object zxborder = DBUtil.getField("to8to_sale", "zxborder", "sid", String.valueOf(sid));
        return zxborder == null ? "" : zxborder.toString();
    }

    private static ZXBOrder getOrderInfoByTid(int tid)
    {
        BoolFilterBuilder boolFilter = FilterBuilders.boolFilter();
        boolFilter.must(FilterBuilders.termFilter("ext.order.tid", tid));
        boolFilter.must(FilterBuilders.termFilter("ext.isassign", 0));//isassign 0未分配；1已分配。 已分配的不再处理。
        QueryBuilder queryBuilder = QueryBuilders.filteredQuery(QueryBuilders.matchAllQuery(), boolFilter);
        SearchResponse resp = ESUtil.es.prepareSearch().setTypes(TYPE_APPLY).setQuery(queryBuilder).setSize(1).execute().actionGet();
        SearchHit[] hits = resp.getHits().getHits();
        ZXBOrder order = new ZXBOrder();
        if (hits.length > 0)
        {
            SearchHit hit = hits[0];
            Map<String, Object> map = hit.getSource();

            order.setHead_order(map.get("head_order").toString());
            order.setEnd_order(map.get("end_order").toString());
            order.setPriceleve(Integer.parseInt(map.get("pricelevel").toString()));
        }
        return order;
    }

    private static List<ExtObj> getProject(int cityid)
    {
        List<ExtObj> list = new ArrayList<ExtObj>();

        BoolFilterBuilder boolFilter = FilterBuilders.boolFilter();
        boolFilter.must(FilterBuilders.rangeFilter("ext.ftime").lt(Utils.getNowWithSecond()));
        boolFilter.must(FilterBuilders.termFilter("ext.isassign", 0));
        boolFilter.must(FilterBuilders.termFilter("cityid", cityid));
        boolFilter.must(FilterBuilders.termFilter("ispass", 1));

        QueryBuilder queryBuilder = QueryBuilders.filteredQuery(QueryBuilders.matchAllQuery(), boolFilter);
        SearchResponse resp =
            ESUtil.es.prepareSearch().setTypes(TYPE_APPLY).setQuery(queryBuilder).addSort("ext.stime", ASC).setSize(10000).execute().actionGet();

        SearchHit[] hits = resp.getHits().getHits();
        for (SearchHit hit : hits)
        {
            Map<String, Object> map = hit.getSource();

        }

        return list;
    }

    private static void insertZXBOrderLog(int type, ExtObj ext, int cityid, int count, Connection connect)
    {
        try
        {
            String subject = String.format("轮标记录%s-开始", cityid);
            String content =
                String.format("结投时间:%s,分配时间:%s,轮标项目，总数:%s,城市id:%s", Utils.formatWithSecond(ext.getFtime()), DateUtil.format(new Date()), count, cityid);
            String sql =
                String.format("insert into zxb_order_log(subject,content,puttime) values(%s,%s,%s)", subject, content, Utils.getNowWithSecond());
            logger.info("Sql: " + sql);
            Statement stat = connect.createStatement();
            String str = stat.execute(sql, Statement.RETURN_GENERATED_KEYS) ? "Succ" : "fail";
            logger.info(String.format("Insert into zxb_order_log %s!", str));
        }
        catch (SQLException e)
        {
            logger.error("Insert into zxb_order_log SQL操作异常！{} \n {}", e, LogUtil.logStackTrace(e));
        }
    }
}
